package com.tom.architect02.other.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * 对里面的子控件，摆放到ViewGroup哪个位置 做控制。
 *
 */
public class MNViewGroup extends ViewGroup {
    private int mWidth;
    private int mHeight;

    public MNViewGroup(Context context) {
        this(context, null);
    }
    public MNViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MNViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        measureChildren(widthMeasureSpec,heightMeasureSpec);
        /**
         * 自定义ViewGroup时，应该从哪些方面进行考虑？
         * 以下代码，虽然都是在计算自定义viewGroup中的子view，但是这些子view的计算都是为了确定viewGroup的大小，以便最终摆放child。
         * **/
        int childCount = getChildCount();
        if (childCount == 0) {
            // viewGroup 里没有任何子view，那么你ViewGroup 设置多大，就显示多大；
            // 但是当你是wrap_content的时候，就直接设置为0
            setMeasuredDimension(measureWidthOrHeight(widthMeasureSpec), measureWidthOrHeight(heightMeasureSpec));
        } else { // 有子view
            // 如果，viewGroup指定的具体的值，resultSize就是你指定的值；
            // 如果viewGroup是wrap_content，resultSize就应该等于子view相加(宽高)；
            int childViewsWidth = 0; // 所有子元素的宽度：子view的最大值
            int childViewsHeight = 0; // 高度

            int childViewsMarginLeft = 0; // 处理child的margin值
            int childViewsMarginRight = 0;
            int childViewsMarginTop = 0;
            int childViewsMarginBottom = 0;

            for (int i = 0; i < childCount; i++) {
                View childView = getChildAt(i);
                // 循环子view，并且测量一下；确定ViewGroup的大小。

                measureChild(childView, widthMeasureSpec, heightMeasureSpec);
                childViewsWidth = Math.max(childViewsWidth, childView.getMeasuredWidth());// 得到子view中宽度最大的那个
                childViewsHeight += childView.getMeasuredHeight();// 得到所有子view的高度的和。此时由于还没有layout，getHeight()的值为0.

                // 处理child的 margin
                // View的 MeasureSpec 由父容器的MeasureSpec 以及自身的LayoutParams共同决定。
                MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
                childViewsMarginTop += lp.topMargin;
                childViewsMarginBottom += lp.bottomMargin;
                // 计算最大的marginLeft, marginRight 的值
                childViewsMarginLeft = Math.max(childViewsMarginLeft, lp.leftMargin);
                childViewsMarginRight = Math.max(childViewsMarginRight, lp.rightMargin);
            }
            mWidth = childViewsWidth + childViewsMarginLeft + childViewsMarginRight;
            mHeight = childViewsHeight + childViewsMarginTop + childViewsMarginBottom;
            setMeasuredDimension(measureWidthOrHeight(widthMeasureSpec, mWidth), measureWidthOrHeight(heightMeasureSpec, mHeight));
        }
    }

    // 根据模式，确定ViewGroup的宽高最终的值。
    private int measureWidthOrHeight(int measureSpec, int widthOrHeight) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = widthOrHeight;
        }
        return result;
    }

    // 测量宽高值
    // viewGroup 里没有任何子view，那么你ViewGroup 设置多大，就显示多大；
    // 但是当你是wrap_content的时候，就直接设置为0
    private int measureWidthOrHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) { // 指定固定值100 或 match_parent
            result = specSize;
        } else { // wrap_content
            result = 0;
        }
        return result;
    }

    // 摆放child，要处理margin。
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//        int childCount = getChildCount();
//        for(int i=0;i<childCount;i++){
//            View childView = getChildAt(i);
//            childView.getWidth();
//            System.out.println("=====>"+childView.getMeasuredHeight()+" "+childView.getMeasuredWidth());
//            childView.layout(l, i*childView.getMeasuredHeight(), childView.getMeasuredWidth(),
//                    (i+1)*childView.getMeasuredHeight());
//        }
        // getMeasuredWidth() 和 getWidth()区别
        // 仅仅只是获取值的时机不同而已；
        // getMeasuredWidth： 要先测量onMeasure，才能拿到值。
        // getWidth： 如果没有调用onLayout，getWidth会是0。onLayout后，getWidth才能拿到值。

        int left, top, right, bottom;
        int countTop = 0;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams(); // 处理margin
            left = lp.leftMargin; // 左边界
            top = countTop + lp.topMargin; // 上边界
            right = left + childView.getMeasuredWidth(); // 右边界
            bottom = top + childView.getMeasuredHeight(); // 底边界
            childView.layout(left, top, right, bottom); // 摆放 child

            // 下一个控件绘制的高度就应该是加上  上一个控件的高度(bottom - top) 以及上一个控件它涉及的margin高度(lp.topMargin + lp.bottomMargin)；
            countTop += ((bottom - top) + lp.topMargin + lp.bottomMargin);
        }
    }

    // 必须重写的方法 MarginLayoutParams
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas); // 子控件自己有onDraw方法。ViewGroup中这个方法作用不大。
    }

}
